/*
 * SPI.c
 *
 * Created: 04.01.2012 22:15:37
 *  Author: Luke
 */ 

#include <avr/io.h>
#include <stdint.h>
#include "SPI.h"

void spiInit(void)
{
	/* NoINT, Enable, MSB first, Master, CPOL0, CPHA0, fosc/4 */
	SPCR = _BV(SPE) | _BV(MSTR);
	DDRB |= _BV(PORTB5) | _BV(PORTB3);
}



void spiSetSpeed(uint8_t spi_speed)
{
    /*
	SPI Speeds @ 8MHz
    SPR1:0 fSPI  fSPI&SPI2x
    0:0    2M    4M
    0:1    500k  1M
    1:0    125k  250k
    1:1    62.5k 125k
    */

    SPCR &= ~(0x03); //clear SPR
    SPCR |= spi_speed & 0x03;

    if (spi_speed & 0x04)
        SPSR |= _BV(SPI2X);
    else
        SPSR &= ~_BV(SPI2X);	
}

void spiSendByte(uint8_t data)
{
	SPDR = data;
}

uint8_t spiSendByteWait(uint8_t data)
{
	spiSendByte(data);
	while(!(SPSR & _BV(SPIF)));
    return SPDR;
}

void spiSendWord(uint16_t data)
{
	uint8_t* data_byte = ((uint8_t*)&data)+1;
	spiSendByteWait(*data_byte);
	data_byte--;
	spiSendByte(*data_byte);
}

uint16_t spiSendWordWait(uint16_t data)
{
    uint16_t result;
	uint8_t* data_byte = ((uint8_t*) &data)+1;
    uint8_t* result_byte = (uint8_t*) &result;
    
	*result_byte = spiSendByteWait(*data_byte);
	data_byte--;
    result_byte++;
	*result_byte = spiSendByteWait(*data_byte);
    
    return result;
}

void spiSendDWordWait(uint32_t* data)
{
	uint8_t* data_byte = ((uint8_t*) data)+3;
    
	spiSendByteWait(*data_byte);
	data_byte--;
	spiSendByteWait(*data_byte);
    data_byte--;
	spiSendByteWait(*data_byte);
	data_byte--;
	spiSendByteWait(*data_byte);
}